<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0,minimum-scale=1.0,maximum-scale=1.0" />
    <meta name="author" content="火星科技 http://mars3d.cn " />
    <meta name="apple-touch-fullscreen" content="yes" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black" />
    <meta name="format-detection" content="telephone=no" />
    <meta name="x5-fullscreen" content="true" />
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
    <!-- 标题及搜索关键字 -->
    <meta name="keywords" content="火星科技,cesium,3D,GIS,marsgis,三维,地球,地图,开发,框架,系统,示例,资料,模型,离线,外包,合肥,安徽,中国" />
    <meta
      name="description"
      content="火星科技 合肥火星 合肥火星科技 合肥火星科技有限公司 leaflet leaflet框架 leaflet开发 cesium cesium开发 cesium框架 三维 地球 模型  gis marsgis 地图离线 地图开发 地图框架 地图外包 框架 开发 外包  地图离线 二维地图 三维地图 全景漫游 地理信息系统 云GIS 三维GIS GIS平台 WebGIS"
    />

    <link rel="shortcut icon" type="image/x-icon" href="http://mars3d.cn/favicon.ico" />
    <title>铁路仿真 | Mars3D | 三维地图 | 火星科技 | 合肥火星科技有限公司</title>

    <!--第三方lib-->
    <script
      type="text/javascript"
      src="../lib/include-lib.js"
      libpath="../lib/"
      include="jquery,font-awesome,echarts,bootstrap,layer,haoutil,turf,mars3d"
    ></script>

    <link href="css/style.css" rel="stylesheet" />
  </head>

  <body class="dark">
    <!--加载前进行操作提示，优化用户体验-->
    <div id="mask" class="signmask" onclick="removeMask()"></div>

    <div id="mars3dContainer" class="mars3d-container"></div>

    <div class="infoview">
      <div id="section" style="width: 400px; height: 250px"></div>
    </div>

    <script src="./js/common.js"></script>
    <script type="text/javascript">
      "use script"; //开发环境建议开启严格模式

      var map;
      var graphicLayer;

      //时间控制参数
      var args = {
        space: 100,
        time: 5,
        martTimeInter: null,
        cleanTimeInter: null,
      };

      function initMap(options) {
        //合并属性参数，可覆盖config.json中的对应配置
        var mapOptions = mars3d.Util.merge(options, {
          scene: {
            center: {
              lat: 31.799613,
              lng: 117.27357,
              alt: 72.55,
              heading: 59.8,
              pitch: -18,
              roll: 0,
            },
          },
          control: {
            animation: true, //是否创建动画小器件，左下角仪表
            timeline: true, //是否显示时间线控件
          },
        });

        //创建三维地球场景
        map = new mars3d.Map("mars3dContainer", mapOptions);

        //创建Graphic图层
        graphicLayer = new mars3d.layer.GraphicLayer();
        map.addLayer(graphicLayer);

        //合肥高铁
        var coors = [
          [117.277697, 31.800233, 45],
          [117.262022, 31.798983, 45],
          [117.229506, 31.793351, 45],
          [117.215719, 31.791085, 45],
          [117.207234, 31.79079, 45],
          [117.180246, 31.790688, 45],
          [117.168311, 31.789785, 45],
          [117.152322, 31.789855, 45],
          [117.125297, 31.788849, 45],
          [117.091144, 31.787516, 45],
        ];

        var positions = mars3d.PointTrans.lonlats2cartesians(coors);

        //插值求新路线（按固定间隔米数插值） positions输入的值需为笛卡尔空间xyz坐标数组
        var positionsNew = mars3d.PolyUtil.interLine(positions, {
          minDistance: 20, //间隔20米
        });

        //求对比的贴地地面高度（用于echarts展示）
        mars3d.PolyUtil.computeSurfacePoints({
          scene: map.scene,
          positions: positionsNew, //需要计算的源路线坐标数组
          callback: function (raisedPositions, noHeight) {
            //raisedPositions为含高程信息的新坐标数组，noHeight为标识是否存在无地形数据。
            console.log(raisedPositions);

            inintRoad(positionsNew, raisedPositions);
          },
        });
      }

      //构造动态高铁   positions:设计的路线    positionsTD地面的贴地路线（用于比较）
      function inintRoad(positionsSJ, positionsTD) {
        var heightArray = [];
        var heightTDArray = [];
        var mpoints = [];
        for (let i = 0; i < positionsSJ.length; i++) {
          let position = positionsSJ[i];
          let carto = Cesium.Cartographic.fromCartesian(position);
          let x = Cesium.Math.toDegrees(carto.longitude);
          let y = Cesium.Math.toDegrees(carto.latitude);

          let height = mars3d.Util.formatNum(carto.height); //设计高度  当小数点后面的数字一致时，会省略小数点，不显示
          let tdHeight = mars3d.Util.formatNum(Cesium.Cartographic.fromCartesian(positionsTD[i]).height); //地面高度

          heightArray.push(height);
          heightTDArray.push(tdHeight);
          mpoints.push([x, y, height, tdHeight]);
        }

        // 距离数组
        var positionsLineFirst = positionsTD[0];
        var distanceArray = positionsTD.map(function (data) {
          return Math.round(Cesium.Cartesian3.distance(data, positionsLineFirst)); //计算两点之间的距离,返回距离
        });

        //显示echarts
        drawHeightToDistanceEcharts(heightArray, heightTDArray, distanceArray);

        // 画线
        var primitive = new mars3d.graphic.PolylinePrimitive({
          id: "设计路线",
          positions: positionsSJ,
          style: {
            width: 3,
            color: Cesium.Color.RED,
            materialType: mars3d.MaterialType.PolylineDash, //虚线
            dashLength: 20,
          },
        });
        graphicLayer.addGraphic(primitive);

        var primitiveTD = new mars3d.graphic.PolylinePrimitive({
          id: "贴地路线",
          positions: positionsTD,
          style: {
            width: 3,
            color: Cesium.Color.YELLOW,
          },
        });
        graphicLayer.addGraphic(primitiveTD);

        //=================计算路线====================
        var start = map.clock.currentTime.clone();

        var counts = mpoints.length;

        var arrProperty = [];

        //16组车身+头尾2个车头 共18组
        for (let j = 0; j < 18; j++) {
          let stime = Cesium.JulianDate.addSeconds(start, j, new Cesium.JulianDate()); //每隔j秒，添加一次时间

          let property = new Cesium.SampledPositionProperty();

          for (let i = 0; i < counts; i++) {
            let time = Cesium.JulianDate.addSeconds(stime, i + 1, new Cesium.JulianDate());
            let point = Cesium.Cartesian3.fromDegrees(mpoints[i][0], mpoints[i][1], mpoints[i][2] + 0.5);
            property.addSample(time, point); //添加新样本，时间、位置
          }

          property.setInterpolationOptions({
            interpolationDegree: 1,
            interpolationAlgorithm: Cesium.LinearApproximation,
          });

          arrProperty.push(property);
        }

        //=================时间相关====================

        let stop = Cesium.JulianDate.addSeconds(start, counts + 60, new Cesium.JulianDate());
        map.clock.startTime = start.clone();
        map.clock.stopTime = stop.clone();
        map.clock.currentTime = start.clone();
        map.clock.multiplier = 1; //当前速度，默认为1
        map.clock.shouldAnimate = true; //是否开启时钟动画，默认true
        // map.clock.clockRange = Cesium.ClockRange.LOOP_STOP; //到达终止时间后循环

        if (map.viewer.timeline) {
          map.viewer.timeline.zoomTo(start, stop);
        }

        let availability = new Cesium.TimeIntervalCollection([
          new Cesium.TimeInterval({
            start: start,
            stop: Cesium.JulianDate.addSeconds(start, counts, new Cesium.JulianDate()),
          }),
        ]);

        //=================添加高铁车头================
        let graphicHead = addTrainHead(arrProperty[0], availability);
        map.trackedEntity = graphicHead.entity; //设置相机的视角跟随的Entity实例

        //=================添加车身====================
        let len = arrProperty.length;
        for (let j = 1; j < len - 1; j++) {
          addTrainBody(arrProperty[j], availability);
        }

        //=================添加高铁车尾================
        addTrainHead(arrProperty[len - 1], availability, true); //车尾部的反向车头

        //==============添加铁路，定时更新================
        addRailway(graphicHead, mpoints);

        //==============更新echarts================
        let lastDistance;

        function locTrain() {
          let t = parseInt(map.clock.currentTime.secondsOfDay - map.clock.startTime.secondsOfDay); //时间差

          if (t >= heightArray.length) {
            //高铁运行结束之后
            clearInterval(args.martTimeInter);
            clearInterval(args.cleanTimeInter);
            return;
          }
          if (lastDistance == t) {
            return;
          }
          lastDistance = t;
          updateEchartsDistance(t, heightArray[t]);
        }
        args.martTimeInter = setInterval(locTrain, 100);
      }

      //添加车头
      function addTrainHead(position, availability, rotatePI) {
        var graphicModel = new mars3d.graphic.ModelEntity({
          name: "和谐号车头",
          position: position,
          orientation: new Cesium.VelocityOrientationProperty(position),
          availability: availability,
          style: {
            url: "//data.mars3d.cn/gltf/mars/train/heada.glb",
            scale: 0.001,
            minimumPixelSize: 16,
            heading: rotatePI ? 90 : -90,
          },
        });
        graphicLayer.addGraphic(graphicModel);
        return graphicModel;
      }

      //添加车身
      function addTrainBody(position, availability) {
        var graphicModel = new mars3d.graphic.ModelEntity({
          name: "和谐号车身",
          position: position,
          orientation: new Cesium.VelocityOrientationProperty(position),
          availability: availability,
          style: {
            url: "//data.mars3d.cn/gltf/mars/train/body.glb",
            scale: 0.001,
            minimumPixelSize: 16,
            heading: -90,
          },
        });
        graphicLayer.addGraphic(graphicModel);
        return graphicModel;
      }

      //添加铁路，定时更新
      function addRailway(graphicHead, mpoints) {
        let positions = [];
        let orientations = [];

        let times = graphicHead.position._property._times;
        let start = times[0].clone();
        let counts = times.length;

        for (let k = 1; k < counts; k++) {
          let time = times[k];

          let position = graphicHead.position.getValue(time);
          positions.push(position);

          let orientation = graphicHead.orientation.getValue(time);
          orientations.push(orientation);
        }

        let i = 0;
        let roadNum = 80;

        function addroad() {
          let space = Math.round(map.clock.currentTime.secondsOfDay - map.clock.startTime.secondsOfDay);
          let spa = space + args.space;
          if (spa > counts) {
            spa = counts;
          }
          for (; i < spa; i++) {
            let availability = new Cesium.TimeIntervalCollection([
              new Cesium.TimeInterval({
                start: Cesium.JulianDate.addSeconds(start, -roadNum + i, new Cesium.JulianDate()),
                stop: Cesium.JulianDate.addSeconds(start, roadNum + i, new Cesium.JulianDate()),
              }),
            ]);

            // 当高度在地下时，添加地下隧道
            if (mpoints[i][2] - mpoints[i][3] < -20 || (i > 2 && mpoints[i - 3][2] - mpoints[i - 3][3] < -20)) {
              // mpoints[i][2] -- 设计高度；mpoints[i][3] -- 贴地高度
              let id = "s" + i;
              let graphic = graphicLayer.getGraphicById(id);
              if (!graphic) {
                let graphicModel = new mars3d.graphic.ModelEntity({
                  id: id,
                  position: positions[i],
                  orientation: orientations[i],
                  availability: availability,
                  style: {
                    url: "//data.mars3d.cn/gltf/mars/railway/suidao.glb",
                    scale: 0.001,
                  },
                });
                graphicLayer.addGraphic(graphicModel);
              } else {
                graphic.entity.availability._intervals[0].stop.secondsOfDay = availability._intervals[0].stop.secondsOfDay;
              }
            }

            // 添加轨道地面
            let id = "xl" + i;
            let graphic = graphicLayer.getGraphicById(id);
            if (!graphic) {
              let graphicModel = new mars3d.graphic.ModelEntity({
                id: id,
                position: positions[i],
                orientation: orientations[i],
                availability: availability,
                style: {
                  url: "//data.mars3d.cn/gltf/mars/railway/railway.glb",
                  scale: 0.001,
                },
              });
              graphicLayer.addGraphic(graphicModel);
            } else {
              graphic.entity.availability._intervals[0].stop.secondsOfDay = availability._intervals[0].stop.secondsOfDay;
            }

            //添加轨道支架
            if (mpoints[i][2] - mpoints[i][3] > 20 && i % 5 == 0) {
              let id = "xq" + i;
              let graphic = graphicLayer.getGraphicById(id);
              if (!graphic) {
                let graphicModel = new mars3d.graphic.ModelEntity({
                  id: id,
                  position: positions[i],
                  orientation: orientations[i],
                  availability: availability,
                  style: {
                    url: "//data.mars3d.cn/gltf/mars/railway/bridge.glb",
                    scale: 0.001,
                  },
                });
                graphicLayer.addGraphic(graphicModel);
              } else {
                graphic.entity.availability._intervals[0].stop.secondsOfDay = availability._intervals[0].stop.secondsOfDay;
              }
            }

            //添加轨道边的柱子
            if (i % 12 == 0) {
              let id = "xd" + i;
              let graphic = graphicLayer.getGraphicById(id);
              if (!graphic) {
                let graphicModel = new mars3d.graphic.ModelEntity({
                  id: id,
                  position: positions[i],
                  orientation: orientations[i],
                  availability: availability,
                  style: {
                    url: "//data.mars3d.cn/gltf/mars/railway/jiazi.glb",
                    scale: 0.001,
                  },
                });
                graphicLayer.addGraphic(graphicModel);
              } else {
                graphic.entity.availability._intervals[0].stop.secondsOfDay = availability._intervals[0].stop.secondsOfDay;
              }
            }
          }

          //移除铁路
          for (let j = args.statate; j < args.statate - args.space; j++) {
            removeGraphic("s" + j);
            removeGraphic("xl" + j);
            removeGraphic("xq" + j);
            removeGraphic("xd" + j);
            args.statate = j;
          }
        }

        addroad();

        args.cleanTimeInter = setInterval(addroad, args.time);
        args.statate = 0;
      }

      function removeGraphic(id) {
        let graphic = graphicLayer.getGraphicById(id);
        if (graphic) {
          if (graphic.entity.availability._intervals[0].stop.secondsOfDay < map.clock.currentTime.secondsOfDay) {
            graphic.remove(true);
          }
        }
      }

      //图表
      var myChart;

      //生成echarts图表
      function drawHeightToDistanceEcharts(heightArray, heightTDArray, distanceArray) {
        if (myChart == null) {
          myChart = echarts.init(document.getElementById("section"), "dark");
        }

        var option = {
          title: {
            text: "断面图",
          },
          tooltip: {
            trigger: "axis",
            axisPointer: {
              type: "cross",
            },
          },
          toolbox: {
            show: false,
            feature: {
              saveAsImage: {},
            },
          },
          legend: {
            data: ["地形高程", "设计高程"],
          },
          xAxis: {
            type: "category",
            boundaryGap: false,
            data: distanceArray,
          },
          yAxis: {
            type: "value",
            axisLabel: {
              formatter: "{value} 米",
            },
            axisPointer: {
              snap: true,
            },
          },
          dataZoom: [
            {
              type: "inside",
            },
            {
              start: 0,
              end: 10,
              handleIcon:
                "M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z",
              handleSize: "80%",
              handleStyle: {
                color: "#fff",
                shadowBlur: 3,
                shadowColor: "rgba(0, 0, 0, 0.6)",
                shadowOffsetX: 2,
                shadowOffsetY: 2,
              },
            },
          ],
          // visualMap: {
          //     show: false,
          //     dimension: 0,
          //     pieces: [{ "gt": 0, "lte": 635 }]
          // },
          series: [
            {
              name: "地形高程",
              type: "line",
              smooth: true,
              itemStyle: {
                normal: {
                  color: "rgb(255, 255, 0)",
                },
              },
              data: heightTDArray,
            },
            {
              name: "设计高程",
              type: "line",
              smooth: true,
              itemStyle: {
                normal: {
                  color: "rgb(255, 70, 131)",
                },
              },
              data: heightArray,
              markPoint: undefined,
            },
          ],
        };
        myChart.setOption(option, true);

        // myChart.on('click', function (param) {
        //     map.trackedEntity = undefined;
        //     map.camera.flyTo({
        //         destination: Cesium.Cartesian3.fromDegrees(points[param.dataIndex][0], points[param.dataIndex][1], height + 30)
        //     });
        // });
      }

      function updateEchartsDistance(loc, height) {
        if (!myChart) {
          return;
        }

        var markPoint = {
          data: [
            {
              name: "车",
              value: "车",
              xAxis: loc + 5,
              yAxis: height,
            },
          ],
        };

        // 填入数据,根据名字对应到相应的系列
        myChart.setOption({
          series: [
            {
              name: "设计高程",
              markPoint: markPoint,
            },
          ],
        });
      }
    </script>
  </body>
</html>
